package com.woniuxy.tfss.web;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.woniuxy.tfss.AlipayConfig;
import com.woniuxy.tfss.entity.*;
import com.woniuxy.tfss.service.*;
import com.woniuxy.tfss.utils.MyUtils;
import com.woniuxy.tfss.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;

@Controller
@RequestMapping("order")
public class OrderController {
    @Autowired(required = false)
    OrderService orderService;

    @Autowired(required = false)
    UserService userService;

    @Autowired
    private RiderService riderService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ItemService itemService;

    @Autowired
    private DiscountService discountService;

    @Autowired
    private UARecordService userAccountRecordService;

    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private AddressService addressService;

    /**
     * 个人中心查询用户订单
     *
     * @param flag    标识变量，用于区别查询信息
     *                list--全部订单 today--今日订单 waitTake--待取件 Riding--配送中 Received--待评价 cancel--取消
     * @param session
     * @param model
     * @return
     */
    @GetMapping("{flag}")
    public String getTodayOrder(@PathVariable String flag, HttpSession session, Model model) {
        User user = (User) session.getAttribute("user");
        if (user == null) {
            model.addAttribute("user", new User());
            return "userLogin";
        }
        List<Order> orders = null;
        if (flag.equals("list")) {
            orders = orderService.getByUserId(user.getId());
        }
        if (flag.equals("today")) {
            orders = orderService.getTodayOrder(user.getId());
        }
        if (flag.equals("waitTake")) {
            orders = orderService.getByStatus(user.getId(), Order.WAITTAKE);
        }
        if (flag.equals("riding")) {
            orders = orderService.getByStatus(user.getId(), Order.RIDING);
        }
        if (flag.equals("received")) {
            orders = orderService.getByStatus(user.getId(), Order.RECEIVED);

        }
        if (flag.equals("cancel")) {
            orders = orderService.getByStatus(user.getId(), Order.CANCEL);
        }
        Iterator<Order> iter = orders.iterator();
        while (iter.hasNext()) {
//执行过程中会执行数据锁定，性能稍差，若在循环过程中要去掉某个元素只能调用iter.remove()方法。
            Order o = iter.next();
            if (o.getStatus().equals(Order.DELETED)) {
                iter.remove();
            }
        }
        model.addAttribute("orders", orders);
        model.addAttribute("flag", flag);
        return "member_orders";
    }

    /**
     * 删除订单（逻辑删除）
     *
     * @param orderId
     * @param resp
     * @throws IOException
     */
    @PostMapping("del")
    @ResponseBody
    public ResponseEntity delOrder(String orderId, HttpServletResponse resp) throws IOException {
        Order order = (Order) orderService.getById(orderId);
        if(order.getStatus().equals(Order.NOTPAYCANCEL)){
            order.setRiderId(null);
        }
        order.setStatus(Order.DELETED);
        orderService.updateById(order);
//        resp.sendRedirect("/order/list");
        return ResponseEntity.SUCCESS;
    }

    @GetMapping("create")
    public String orderCreate(Model model) {//点下单返回订单填写页面
        List<Category> categories = categoryService.list();
        model.addAttribute("categories", categories);//所有的物品种类,下拉框使用
        return "order_create";
    }

    @GetMapping("add")
    public String orderAdd(Order order, Model model, HttpSession session) {//骑手分配完毕收到状态码200后返回订单确认界面,进行一次数据库的更新
        User user = (User) session.getAttribute("user");
        order.setUserId(user.getId());
        order.setNo(MyUtils.getOrderNo());
        order.setOrderTime(MyUtils.getNow());
        order.setSendInfo(order.getSendName() + " " + order.getSendPhone() + " " + order.getSendAddress());
        order.setRecInfo(order.getRecName() + " " + order.getRecPhone() + " " + order.getRecAddress());
        order.setExpectTime(10 + order.getExpectTime() / 60);//高德地图预计时间(秒)加上10分钟为闪送预计时间
        List<Item> items = order.getItems();
        BigDecimal totalWeight = new BigDecimal("0.00");
        BigDecimal totalMoney = new BigDecimal("0.00");
        for (int i = 0; i < items.size(); i++) {
            totalWeight = totalWeight.add(items.get(i).getWeight());
            totalMoney = totalMoney.add(MyUtils.itemPrice(order.getDistance().intValue(), items.get(i).getCategoryId(), categoryService));
        }
        if (totalWeight.compareTo(new BigDecimal(10.00)) < 1) {//总重量小于等于10kg不加收额外重量费用
            order.setTotalMoney(totalMoney);
        } else {//超过10kg的情况,超过1kg加收2元(无补足,直接乘算),四舍五入保留两位
            order.setTotalMoney(totalMoney.add(totalWeight.subtract(new BigDecimal(10.00)).multiply(new BigDecimal("2.00"))).setScale(2));
        }
        order.setWeight(totalWeight.setScale(2));
        order.setDistance(order.getDistance().divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP));
        order.setStatus(Order.WAITCONFIRM);
        if (order.getArrange().equals(Order.ISARRANGE)) {//预约下单的情况
            order.setRiderId(null);
        } else {//即时下单的情况
            order.setArrange(Order.NOTARRANGE);
            order.setAcceptTime(MyUtils.getNow());
            order.setArrangeTime(null);
        }
        orderService.save(order);
        for (int i = 0; i < items.size(); i++) {//更新订单详情的数据库
            Item item = items.get(i);
            item.setOrderId(order.getId());
            itemService.save(item);
        }
        model.addAttribute("order", order);
        model.addAttribute("discounts", userService.getDiscountsByUserId(user.getId()));//将用户有的优惠券带回页面
        return "order_confirm";
    }

    @GetMapping("cof/{orderId}")
    public String orderCof(@PathVariable Integer orderId,Model model,HttpSession session){
        User user = (User) session.getAttribute("user");
        Order order=orderService.getById(orderId);
        model.addAttribute("order", order);
        model.addAttribute("discounts", userService.getDiscountsByUserId(user.getId()));//将用户有的优惠券带回页面
        return "order_confirm";
    }
    @PostMapping("confirm/{orderId}/{discountId}/{payType}")
    @ResponseBody
    public ResponseEntity<?> orderConfirm(HttpServletRequest req, HttpServletResponse resp, @PathVariable Integer orderId, @PathVariable Integer discountId, @PathVariable String payType, HttpSession session) throws IOException {//确认下单,进行支付逻辑和数据库的更新
        User user = (User) session.getAttribute("user");
        Order order = orderService.getById(orderId);
        if (!order.getStatus().equals(Order.WAITCONFIRM)) {
            return ResponseEntity.WRONGSTATUS;//防止错误状态
        }
        Discount discount = discountService.getById(discountId);
        order.setPayType(payType);
        order.setDiscountId(discountId);
        BigDecimal realMoney;//实付款
        if (discountId == 0) {//没有使用优惠券
            realMoney = order.getTotalMoney();
        } else {
            realMoney = (order.getTotalMoney().multiply(discount.getDiscount())).setScale(2);
        }
        order.setRealMoney(realMoney);

        if (Order.USERMONEY.equals(order.getPayType())) {//余额支付逻辑
            if (user.getMoney().compareTo(realMoney) == -1) {//余额不足的情况
                return ResponseEntity.NOMONEY;
            } else {
                user.setMoney(user.getMoney().subtract(realMoney));
                userService.updateById(user);//减少用户的余额
                userService.reduceDiscount(user.getId(), discountId);//删除使用了的优惠券
                UserAccountRecord uar = new UserAccountRecord();//更新消费记录表
                uar.setOrderNo(order.getNo());
                uar.setTime(MyUtils.getNow());
                uar.setMoney(order.getRealMoney());
                uar.setUserId(order.getUserId());
                uar.setType("0");
                userAccountRecordService.save(uar);
                //余额支付成功以后
                if (order.getArrange().equals(Order.ISARRANGE)) {//预约下单的情况
                    order.setStatus(Order.WAIT);
                    orderService.updateById(order);
                    return ResponseEntity.ARRANGESUCCESS;//成功预约派送
                } else {//即时下单的情况
                    order.setStatus(Order.RIDING);
                    orderService.updateById(order);
                    Rider rider = riderService.getById(order.getRiderId());
                    rider.setWorkStatus(Rider.WORK);
                    riderService.updateById(rider);
                    webSocketServer.sendInfo("r" + order.getRiderId(), new Message<>(901, order));//发消息给指定骑手
                    return ResponseEntity.SUCCESS;//下单成功开始派送
                }
            }
        } else {//支付宝逻辑
            orderService.updateById(order);
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
            //设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(AlipayConfig.return_url);
            alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
            //商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no = order.getNo();
            //付款金额，必填
            String total_amount = order.getRealMoney().toString();
            //订单名称，必填
            String subject = "天府闪送";
            //商品描述，可空
            String body = "";
            alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                    + "\"total_amount\":\"" + total_amount + "\","
                    + "\"subject\":\"" + subject + "\","
                    + "\"body\":\"" + body + "\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
            //若想给BizContent增加其他可选请求参数，以增加自定义超时时间参数timeout_express来举例说明
            //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
            //		+ "\"total_amount\":\""+ total_amount +"\","
            //		+ "\"subject\":\""+ subject +"\","
            //		+ "\"body\":\""+ body +"\","
            //		+ "\"timeout_express\":\"10m\","
            //		+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
            //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节
            String result = ""; //请求
            try {
                result = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
            } catch (AlipayApiException e) {
                return ResponseEntity.PAYFAILED;
            }
            resp.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            return new ResponseEntity<>(806, "OK", result);
        }
    }

    @GetMapping("payreturn")
    public String orderPayReturn(HttpServletRequest req, HttpServletResponse resp) {//支付宝付款成功后
        String no = req.getParameter("out_trade_no");
        if (no.contains("TFSS")) {
            Order order = orderService.getByNo(no);
            UserAccountRecord uar = new UserAccountRecord();//更新消费记录表
            uar.setOrderNo(no);
            uar.setTime(MyUtils.getNow());
            uar.setMoney(order.getRealMoney());
            uar.setType("0");
            uar.setUserId(order.getUserId());
            userAccountRecordService.save(uar);
            if (order.getArrange().equals(Order.ISARRANGE)) {//预约下单的情况
                order.setStatus(Order.WAIT);
                orderService.updateById(order);
            } else {//即时下单的情况
                order.setStatus(Order.RIDING);
                orderService.updateById(order);
                Rider rider = riderService.getById(order.getRiderId());
                rider.setWorkStatus(Rider.WORK);
                riderService.updateById(rider);
                webSocketServer.sendInfo("r" + order.getRiderId(), new Message<>(901, order));//发消息给指定骑手
            }
            userService.reduceDiscount(order.getUserId(), order.getDiscountId());//删除使用了的优惠券
        } else if (no.contains("RECH")) {
            UserAccountRecord ua = userAccountRecordService.getByNo(no);
            User user = userService.getById(ua.getUserId());
            user.setMoney(user.getMoney().add(ua.getMoney()));
            userService.updateById(user);
            ua.setStatus(UserAccountRecord.PAYED);
            userAccountRecordService.updateById(ua);
            return "redirect:/user/userAccount";
        }

        return "redirect:/";
    }

    @GetMapping("getById/{id}")
    @ResponseBody
    public ResponseEntity<?> getOrderById(@PathVariable Integer id) {
        return new ResponseEntity<>(orderService.getById(id));
    }

    @GetMapping("robOrder/{orderId}/{riderId}")
    @ResponseBody
    public ResponseEntity<?> robOrder(@PathVariable Integer orderId, @PathVariable Integer riderId) {//抢单逻辑
        Order order = orderService.getById(orderId);
        Rider rider = riderService.getById(riderId);
        if (order.getRiderId() != null) {
            return ResponseEntity.ROBED;//单已经被其他骑手抢走
        }
        if (rider.getWorkStatus().equals(Rider.WORK)) {
            return ResponseEntity.WORKED;//骑手还有其他订单未完成
        }
        if (MyUtils.getNow().compareTo(order.getArrangeTime()) <= 0) {//预约时间之前抢单,在预约时间开始配送
            order.setAcceptTime(order.getArrangeTime());
        } else {//超过预约时间半小时内抢单,立即开始配送
            order.setAcceptTime(MyUtils.getNow());
        }
        order.setRiderId(riderId);
        order.setStatus(Order.RIDING);
        orderService.updateById(order);

        rider.setWorkStatus(Rider.WORK);
        riderService.updateById(rider);

        webSocketServer.sendInfo("u" + order.getUserId(), new Message<>(903, order));//发消息给用户
        return ResponseEntity.SUCCESS;//通知骑手抢单成功
    }

    @GetMapping("receive/{orderId}")
    @ResponseBody
    public ResponseEntity receive(@PathVariable Integer orderId) {//确认送达逻辑
        Order order = orderService.getById(orderId);
        order.setGetTime(MyUtils.getNow());
        order.setStatus(Order.RECEIVED);
        orderService.updateById(order);
        Rider rider = riderService.getById(order.getRiderId());
        rider.setWorkStatus(Rider.WAIT);
        webSocketServer.sendInfo("r" + order.getRiderId(), new Message<>(908, order));//发消息给骑手
        if(order.getArrange().equals(Order.ISARRANGE)){
            rider.setProfit(order.getRealMoney().multiply(new BigDecimal(0.4)));
        }else {
            rider.setProfit(order.getRealMoney().multiply(new BigDecimal(0.3)));
        }
        riderService.updateById(rider);
        return ResponseEntity.SUCCESS;//前端判断状态码给用户反馈
    }

    @GetMapping("appeal/{orderId}")
    @ResponseBody
    public ResponseEntity appeal(@PathVariable Integer orderId) {//用户申诉逻辑
        Order order = orderService.getById(orderId);
        order.setGetTime(MyUtils.getNow());
        order.setStatus(Order.NEEDEXAMINE);//订单提交后台审核
        orderService.updateById(order);
        Rider rider = riderService.getById(order.getRiderId());
        rider.setWorkStatus(Rider.WAIT);
        webSocketServer.sendInfo("r" + order.getRiderId(), new Message<>(909, order));//发消息给骑手
        if(order.getArrange().equals(Order.ISARRANGE)){
            rider.setProfit(order.getRealMoney().multiply(new BigDecimal(0.4)));
        }else {
            rider.setProfit(order.getRealMoney().multiply(new BigDecimal(0.3)));
        }
        riderService.updateById(rider);

        return ResponseEntity.SUCCESS;//前端判断状态码给用户反馈
    }
}
